#include "client.h"
#include <iostream>
#include <boost/bind.hpp>

Client::Client(boost::asio::io_service& io_service, 
	const std::string host, short port)
	:m_service(io_service), m_client(io_service)
{
	address addr = address::from_string(host);
	m_client.async_connect(tcp::endpoint(addr, port),
		boost::bind(&Client::onConnect, this, boost::asio::placeholders::error));
}

void Client::sendMessage(const std::string& message)
{
	std::ostream os(&m_requestStream);
	os << message;
	
	async_write(m_client, m_requestStream,
		boost::bind(&Client::onWriteFinish, this,
		boost::asio::placeholders::error,
		boost::asio::placeholders::bytes_transferred));
}

void Client::onConnect(const boost::system::error_code& err)
{
	if (!err)
	{
		async_read(m_client, m_responseStream,
			boost::asio::transfer_at_least(1),
			boost::bind(&Client::onMessage, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred));
	}
	else
		std::cerr << "connect error[" << err.value() << "]: " << err.message() << std::endl;
}

void Client::onMessage(const boost::system::error_code& err,
	std::size_t bytes_transferred)
{
	if (!err)
	{
		size_t length = m_responseStream.size();
		std::string buff(length, '\0');
		m_responseStream.sgetn(&buff[0], length);
		std::cout << "receive: " << buff << std::endl;
		assert(0 == m_responseStream.size());

		async_read(m_client, m_responseStream,
			boost::asio::transfer_at_least(1),
			boost::bind(&Client::onMessage, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred));

	}
	else
		std::cerr << "read error: " << err.message() << std::endl;
}

void Client::onWriteFinish(const boost::system::error_code& err,
	std::size_t bytes_transferred)
{
	if (!err)
		std::cout << "send finish, request stream size is " << m_requestStream.size() << std::endl;
	else
		std::cerr << "write error: " << err.message() << std::endl;
}
